今天花了不少時間在更正Portfolio Allocation中的內容,主要是講解的部分有一些錯誤,今天重新理解了以後修正了前兩天的文章。
在Portfolio Allocation
的教學文章最後,其實有使用pyfolio
庫來繪製一些很專業的獲利分析報表,但我嘗試使用pyfolio
後碰到了很多兼容性問題,始終沒有克服,因此後來我沒有在程式碼中使用pyfolio繪製進階圖表;今天再次嘗試了以後,我決定改成使用quantstats
來繪製這些圖表,從外觀上看起來基本上都差不多,不過差別是pyfolio
已經快10年沒更新了,而quantstats
則是比較新,所以不太會碰到一些跟其他庫(Pandas)的兼容性問題。
安裝pip install quantstats
主要用來產生報表的輸入是daily_return
,包裝了以後程式碼如下:
def generate_quantstats_report(daily_return_df,
output_filename,
title,
benchmark_return_df=None):
"""
Function to generate a QuantStats HTML report with an optional benchmark.
Parameters:
- daily_return_df: Pandas DataFrame containing 'date' and 'daily_return' columns.
- output_filename: The name of the output HTML file for the report.
- title: The title for the report.
- benchmark_return_df: (Optional) Pandas DataFrame or Series with 'date' as index for the benchmark returns.
Returns:
- None. The report will be saved as an HTML file.
"""
# 檢查並轉換 daily_return_df 的 index 為 tz_native (去除時區)
if daily_return_df.index.tz is not None:
daily_return_df.index = daily_return_df.index.tz_convert(None)
# 檢查並轉換 benchmark_return_df 的 index 為 tz_native (去除時區) (如果有提供 benchmark)
if benchmark_return_df is not None and benchmark_return_df.index.tz is not None:
benchmark_return_df.index = benchmark_return_df.index.tz_convert(None)
# 生成 Quantstats HTML 報告
qs.reports.html(daily_return_df,
output=output_filename,
title=title,
benchmark=benchmark_return_df)
print(
f"Quantstats HTML report has been generated and saved as '{output_filename}'."
)
注意:
qs.reports.html
的輸入DataFrame的index要是datetime tz_native的格式
quantstats
有多個繪製的api選擇,我這邊直接使用.html()
產生網頁出來看。
這裡針對把['A2C', 'PPO', 'DDPG', 'SAC', 'TD3']的daily_return
放在一起比較,同時使用dji作為benchmark來比較。
# 創建一個字典來存儲每個模型的 daily_return
daily_returns = {}
for model_name, info in backtest_results.items():
daily_return = info['daily_return']
# 將 'date' 列轉換為 datetime 並設置為索引
daily_return['date'] = pd.to_datetime(daily_return['date'])
daily_return.set_index('date', inplace=True)
daily_returns[model_name] = daily_return['daily_return']
# 將所有模型的 daily_return 合併到一個 DataFrame
daily_returns_df = pd.concat(daily_returns, axis=1)
dji_daily_return_df = copy.deepcopy(dji_daily_return)
dji_daily_return_df.name = 'dji'
generate_quantstats_report(daily_returns_df,
"performance_report.html",
"Performance Report",
benchmark_return_df=dji_daily_return_df)
生成出來的報表